home *** CD-ROM | disk | FTP | other *** search
/ Super PC 34 / Super PC 34 (Shareware).iso / spc / UTIL / DJGPP2 / V2 / DJLSR200.ZIP / src / libc / go32 / gopint.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-01  |  8.2 KB  |  243 lines

  1. /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
  2. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  3. #include <dpmi.h>
  4. #include <go32.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <sys/exceptn.h>
  8.  
  9. /* We enter with only CS known, and SS on a locked 4K stack which
  10.    is *NOT* our SS.  We must set up everthing, including a stack swap,
  11.    then restore it the way we found it.   C. Sandmann 4-93 */
  12.  
  13. /*
  14.  * NOTE: we now store some information in the stack interrupt stack
  15.  *    long 0 = flags    (currently bit 0 = this stack was malloc()ed)
  16.  *    long 1 = block count (if non-zero, users's function won't be called)
  17.  *    long 2 = count of how many times this wrapper has been hit
  18.  *            (note: count includes times when we're recursively
  19.  *                             called and don't call the user's function)
  20.  */
  21.  
  22. #define    STACK_WAS_MALLOCED    (1 << 0)
  23.  
  24. #define    FILL    0x00
  25.  
  26. static unsigned char wrapper_intcommon[] = {
  27. /* 00 */ 0x1e,                /*     push ds                  */
  28. /* 01 */ 0x06,                /*     push es            */
  29. /* 02 */ 0x0f, 0xa0,            /*     push fs                  */
  30. /* 04 */ 0x0f, 0xa8,            /*     push gs                  */
  31. /* 06 */ 0x60,                /*     pusha                    */
  32. /* 07 */ 0x66, 0xb8,            /*     mov ax,            */
  33. /* 09 */ FILL, FILL,            /*         _our_selector    */
  34. /* 0B */ 0x8e, 0xd8,            /*     mov ds, ax               */
  35. /* 0D */ 0xff, 0x05,             /*     incl            */
  36. /* 0F */ FILL, FILL, FILL, FILL,    /*        _call_count        */
  37. /* 13 */ 0x83, 0x3d,            /*     cmpl            */
  38. /* 15 */ FILL, FILL, FILL, FILL,    /*         _in_this_handler    */
  39. /* 19 */ 0x00,                /*         $0            */
  40. /* 1A */ 0x75,                /*     jne            */
  41. /* 1B */ 0x2F,                /*         bypass        */
  42. /* 1C */ 0xc6, 0x05,            /*     movb            */
  43. /* 1E */ FILL, FILL, FILL, FILL,    /*         _in_this_handler     */
  44. /* 22 */ 0x01,                /*         $1            */
  45. /* 23 */ 0x8e, 0xc0,            /*     mov es, ax               */
  46. /* 25 */ 0x8e, 0xe0,            /*     mov fs, ax               */
  47. /* 27 */ 0x8e, 0xe8,            /*     mov gs, ax               */
  48. /* 29 */ 0xbb,                /*     mov ebx,            */
  49. /* 2A */ FILL, FILL, FILL, FILL,    /*         _local_stack        */
  50. /* 2E */ 0xfc,                /*     cld                      */
  51. /* 2F */ 0x89, 0xe1,            /*     mov ecx, esp             */
  52. /* 31 */ 0x8c, 0xd2,            /*     mov dx, ss               */
  53. /* 33 */ 0x8e, 0xd0,            /*     mov ss, ax               */
  54. /* 35 */ 0x89, 0xdc,            /*     mov esp, ebx             */
  55. /* 37 */ 0x52,                /*     push edx                 */
  56. /* 38 */ 0x51,                /*     push ecx                 */
  57. /* 39 */ 0xe8,                /*     call            */
  58. /* 3A */ FILL, FILL, FILL, FILL,    /*         _rmih        */
  59. /* 3E */ 0x58,                /*     pop eax                     */
  60. /* 3F */ 0x5b,                /*     pop ebx                     */
  61. /* 40 */ 0x8e, 0xd3,            /*     mov ss, bx               */
  62. /* 42 */ 0x89, 0xc4,            /*     mov esp, eax             */
  63. /* 44 */ 0xc6, 0x05,            /*     movb            */
  64. /* 46 */ FILL, FILL, FILL, FILL,    /*         _in_this_handler    */
  65. /* 4A */ 0x00,                /*         $0            */
  66. /* 4B */ 0x61,                /* bypass:  popa        */
  67. /* 4C */ 0x90,                /*     nop            */
  68. /* 4D */ 0x0f, 0xa9,            /*     pop gs                   */
  69. /* 4F */ 0x0f, 0xa1,            /*     pop fs                   */
  70. /* 51 */ 0x07,                /*     pop es                   */
  71. /* 52 */ 0x1f                /*     pop ds                   */
  72. };
  73.  
  74. static unsigned char wrapper_intiret[] = {
  75. /* 53 */ 0xcf,                /*     iret                     */
  76. };
  77.  
  78. static unsigned char wrapper_intchain[] = {
  79. /* 53 */ 0x2e, 0xff, 0x2d,        /*     jmp     cs:         */
  80. /* 56 */ FILL, FILL, FILL, FILL,    /*     [_old_int+39]         */
  81. /* 5A */ 0xcf,                /*     iret                     */
  82. /* 5B */ FILL, FILL, FILL, FILL,    /*     old_address         */
  83. /* 5F */ FILL, FILL,            /*     old_segment         */
  84. };
  85.  
  86. unsigned long _go32_interrupt_stack_size = 32256;
  87.  
  88. int _go32_dpmi_lock_data( void *lockaddr, unsigned long locksize )
  89.     {
  90.     unsigned long baseaddr;
  91.     __dpmi_meminfo memregion;
  92.  
  93.     if( __dpmi_get_segment_base_address( _go32_my_ds(), &baseaddr) == -1 ) return( -1 );
  94.  
  95.     memset( &memregion, 0, sizeof(memregion) );
  96.  
  97.     memregion.address = baseaddr + (unsigned long) lockaddr;
  98.     memregion.size    = locksize;
  99.  
  100.     if( __dpmi_lock_linear_region( &memregion ) == -1 ) return( -1 );
  101.  
  102.     return( 0 );
  103.     }
  104.  
  105. int _go32_dpmi_lock_code( void *lockaddr, unsigned long locksize )
  106.     {
  107.     unsigned long baseaddr;
  108.     __dpmi_meminfo memregion;
  109.  
  110.     if( __dpmi_get_segment_base_address( _go32_my_cs(), &baseaddr) == -1 ) return( -1 );
  111.  
  112.     memset( &memregion, 0, sizeof(memregion) );
  113.  
  114.     memregion.address = baseaddr + (unsigned long) lockaddr;
  115.     memregion.size    = locksize;
  116.  
  117.     if( __dpmi_lock_linear_region( &memregion ) == -1 ) return( -1 );
  118.  
  119.     return( 0 );
  120.     }
  121.  
  122. static int _go32_dpmi_chain_protected_mode_interrupt_vector_with_stack(int vector,
  123.     _go32_dpmi_seginfo *info, unsigned char *stack, unsigned long stack_length)
  124. {
  125.   unsigned char *wrapper;
  126.   __dpmi_paddr pm_int;
  127.  
  128. #define    CHECK_STACK()                            \
  129.   if ((stack_length && stack_length < 512) ||                \
  130.         (!stack_length && _go32_interrupt_stack_size < 512))    \
  131.     return 0x8015
  132.  
  133.   CHECK_STACK();
  134.  
  135.   wrapper = (unsigned char *)malloc(sizeof(wrapper_intcommon) +
  136.                              sizeof(wrapper_intchain));
  137.   if (wrapper == 0)
  138.     return 0x8015;
  139.  
  140.   if( _go32_dpmi_lock_data( wrapper,
  141.     sizeof(wrapper_intcommon) + sizeof(wrapper_intchain)) ) return 0x8015;
  142.  
  143. #define    MALLOC_STACK()                    \
  144.   do {                            \
  145.       if (!stack_length) {                \
  146.       stack_length = _go32_interrupt_stack_size;    \
  147.       stack = (char *)malloc(stack_length);        \
  148.       if (stack == 0) {                \
  149.         free(wrapper);                \
  150.         return 0x8015;                \
  151.       }                        \
  152.           if( _go32_dpmi_lock_data( stack,              \
  153.             stack_length) ) return 0x8015;              \
  154.       ((long *)stack)[0] = STACK_WAS_MALLOCED;    \
  155.       } else                        \
  156.       ((long *)stack)[0] = 0;            \
  157.       ((long *)stack)[1] = 0;                \
  158.       ((long *)stack)[2] = 0;                \
  159.   } while (0)
  160.  
  161.   MALLOC_STACK();
  162.  
  163.   __dpmi_get_protected_mode_interrupt_vector(vector, &pm_int);
  164.  
  165.   memcpy(wrapper, wrapper_intcommon, sizeof(wrapper_intcommon));
  166.   memcpy(wrapper+sizeof(wrapper_intcommon), wrapper_intchain,
  167.                              sizeof(wrapper_intchain));
  168.  
  169. #define    FILL_INT_WRAPPER()                        \
  170.   *(short *)(wrapper+0x09) = __djgpp_ds_alias;                \
  171.   *(long  *)(wrapper+0x0F) = (long) stack + 8;                \
  172.   *(long  *)(wrapper+0x15) = (long) stack + 4;                \
  173.   *(long  *)(wrapper+0x1E) = (long) stack + 4;                \
  174.   *(long  *)(wrapper+0x2A) = (long) stack + stack_length;        \
  175.   *(long  *)(wrapper+0x3A) = info->pm_offset - ((long)wrapper + 0x3E);    \
  176.   *(long  *)(wrapper+0x46) = (long) stack + 4
  177.  
  178.   FILL_INT_WRAPPER();
  179.  
  180.   *(long  *)(wrapper+0x56) = (long) wrapper + 0x5B;
  181.   *(long  *)(wrapper+0x5B) = pm_int.offset32;
  182.   *(short *)(wrapper+0x5F) = pm_int.selector;
  183.  
  184.   pm_int.offset32 = (int)wrapper;
  185.   pm_int.selector = _my_cs();
  186.   __dpmi_set_protected_mode_interrupt_vector(vector, &pm_int);
  187.   return 0;
  188. }
  189.  
  190. int _go32_dpmi_chain_protected_mode_interrupt_vector(int vector,
  191.                               _go32_dpmi_seginfo *info)
  192. {
  193.     return _go32_dpmi_chain_protected_mode_interrupt_vector_with_stack(vector,
  194.                          info, (unsigned char *) 0, 0);
  195. }
  196.  
  197. static int _go32_dpmi_allocate_iret_wrapper_with_stack(_go32_dpmi_seginfo *info,
  198.                   unsigned char *stack, unsigned long stack_length)
  199. {
  200.   unsigned char *wrapper;
  201.  
  202.   CHECK_STACK();
  203.  
  204.   wrapper = (unsigned char *)malloc(sizeof(wrapper_intcommon) +
  205.                              sizeof(wrapper_intiret));
  206.  
  207.   if (wrapper == 0)
  208.     return 0x8015;
  209.  
  210.   if( _go32_dpmi_lock_data( wrapper,
  211.     sizeof(wrapper_intcommon) + sizeof(wrapper_intiret)) ) return 0x8015;
  212.  
  213.   MALLOC_STACK();
  214.  
  215.   memcpy(wrapper, wrapper_intcommon, sizeof(wrapper_intcommon));
  216.   memcpy(wrapper+sizeof(wrapper_intcommon), wrapper_intiret,
  217.      sizeof(wrapper_intiret));
  218.  
  219.   FILL_INT_WRAPPER();
  220.  
  221.   info->pm_offset = (int)wrapper;
  222.   info->pm_selector = _my_cs();
  223.   return 0;
  224. }
  225.  
  226. int _go32_dpmi_allocate_iret_wrapper(_go32_dpmi_seginfo *info)
  227. {
  228.     return _go32_dpmi_allocate_iret_wrapper_with_stack(info,
  229.                             (unsigned char *)0, 0);
  230. }
  231.  
  232. int _go32_dpmi_free_iret_wrapper(_go32_dpmi_seginfo *info)
  233. {
  234.   char *stack;
  235.   char *wrapper = (char *)info->pm_offset;
  236.  
  237.   stack = (char *)(*(long *)(wrapper+0x0F) - 8);
  238.   if (*(long *) stack & STACK_WAS_MALLOCED)
  239.       free(stack);
  240.   free(wrapper);
  241.   return 0;
  242. }
  243.